package org.summerframework.component.upload.util;

import org.summerframework.component.upload.type.AUDIO;
import org.summerframework.component.upload.type.VIDEO;
import org.summerframework.core.base.result.DefaultResultCode;
import org.summerframework.core.exception.SystemException;
import org.summerframework.core.exception.WebException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * UploadFileUtil
 *
 * @author 石超
 */
public class UploadFileUtil implements Serializable {

    private String FFMPEGPath;

    private String videoThumbSize;

    private boolean simpleCover;

    public UploadFileUtil(String FFMPEGPath, String videoThumbSize, boolean simpleCover) {
        this.FFMPEGPath = FFMPEGPath;
        this.videoThumbSize = videoThumbSize;
        this.simpleCover = simpleCover;
    }

    private UploadFileUtil() {
    }

    /**
     * 处理文件,暂时保持在temp中
     *
     * @param path     文件地址
     * @param callback 处理完成后回调
     */
    public void uploadFile(String path, UploadFileCallback callback) {
        try {
            uploadFile(new FileInputStream(path), FileUtil.getFileName(path), true, callback);
        } catch (FileNotFoundException e) {
            throw new WebException(DefaultResultCode.ILLEGAL_ARGUMENT, "未找到文件", e);
        }
    }

    public static void copyFile(String srcPath, String realPath) throws IOException {
        FileUtils.copyFile(new File(srcPath), new File(realPath));
    }

    /**
     * 处理文件,暂时保持在temp中
     *
     * @param file     spring上传文件对象
     * @param callback 处理完成后回调
     */
    public void uploadFile(MultipartFile file, UploadFileCallback callback) {
        try {
            uploadFile(file.getInputStream(), file.getName(), true, callback);
        } catch (IOException e) {
            throw new WebException(DefaultResultCode.ILLEGAL_ARGUMENT, "处理文件失败", e);
        }
    }

    /**
     * 处理文件,暂时保持在temp中
     *
     * @param in         流
     * @param fileName   文件名称
     * @param needHandle 是否需要压缩
     * @param callback   处理完成后回调
     */
    public void uploadFile(InputStream in, String fileName, Boolean needHandle, UploadFileCallback callback) {
        try {
            File f = File.createTempFile("tmp", "." + FilenameUtils.getExtension(fileName));
            IOUtils.copy(in, new FileOutputStream(f));
            uploadFile(f, fileName, needHandle, callback);
        } catch (IOException e) {
            throw new SystemException(DefaultResultCode.ILLEGAL_ARGUMENT, "处理文件失败", e);
        }
    }

    /**
     * 处理文件,暂时保持在temp中
     *
     * @param f          流
     * @param fileName   文件名称
     * @param needHandle 是否需要压缩
     * @param callback   处理完成后回调
     */
    public void uploadFile(File f, String fileName, Boolean needHandle, UploadFileCallback callback) {
        List<File> files = new ArrayList<>();

        try {
            UploadFile uploadFile = new UploadFile();
            files.add(f);

            // 根据文件类型进行不同的处理(音频视频压缩)
            if (MediaFile.isImageFileType(f.getAbsolutePath())) {// 图片类型
                uploadFile.setType(1);
            } else if (MediaFile.isAudioFileType(f.getAbsolutePath()) && needHandle) {// 音乐类型
                AudioUploadFile audioUploadFile = new AudioUploadFile();

                if (StringUtils.isNotBlank(FFMPEGPath)) {
                    // 文件转化
                    FFMpegUtil ffmu = new FFMpegUtil(FFMPEGPath, f.getAbsolutePath());

                    // 文件时间
                    audioUploadFile.setTime(ffmu.getRuntime());
                    File mp3 = transfer(ffmu, ".mp3");
                    files.add(mp3);
                    audioUploadFile.putTransferPath(AUDIO.MP3, mp3.getAbsolutePath());

                    if (!simpleCover) {
                        File amr = transfer(ffmu, ".amr");
                        File wav = transfer(ffmu, ".wav");
                        files.add(amr);
                        files.add(wav);
                        audioUploadFile.putTransferPath(AUDIO.AMR, amr.getAbsolutePath());
                        audioUploadFile.putTransferPath(AUDIO.WAV, wav.getAbsolutePath());
                    }

                    // 获取音乐信息
                    String[] infos = MusicUtil.parserMusic(mp3.getAbsolutePath(), fileName).split(",");
                    audioUploadFile.setTitle(infos[0].trim());
                    audioUploadFile.setSinger((infos[1].contains("\\") ? infos[1].replace("\\", "&") : infos[1]).trim());
                    audioUploadFile.setAlbum(infos[2].trim());
                }

                audioUploadFile.setType(2);
                uploadFile = audioUploadFile;
            } else if (MediaFile.isVideoFileType(f.getAbsolutePath()) && needHandle) {// 视频类型
                if (StringUtils.isNotBlank(FFMPEGPath)) {
                    FFMpegUtil ffmu = new FFMpegUtil(FFMPEGPath, f.getAbsolutePath());

                    File file = File.createTempFile("tmp", ".jpg");
                    ffmu.makeScreenCut(file.getAbsolutePath());
                    uploadFile.setTime(ffmu.getRuntime());
                    File mp4 = transfer(ffmu, ".mp4");

                    files.add(file);
                    files.add(mp4);

                    uploadFile.setThumb(file.getAbsolutePath());
                    uploadFile.putTransferPath(VIDEO.MP4, mp4.getAbsolutePath());

                    if (!simpleCover) {
                        File ogv = transfer(ffmu, ".ogv");
                        files.add(ogv);
                        uploadFile.putTransferPath(VIDEO.OGV, ogv.getAbsolutePath());
                    }
                }

                uploadFile.setType(3);
            } else {
                uploadFile.setType(5);
            }

            uploadFile.setSuffix(FileUtil.getExtension(fileName));
            uploadFile.setName(FileUtil.getName(fileName));
            uploadFile.setPath(f.getAbsolutePath());
            callback.callback(uploadFile);
        } catch (Exception e) {
            throw new SystemException(DefaultResultCode.ILLEGAL_ARGUMENT, "处理文件失败", e);
        } finally {
            for (File file : files) {
                FileUtils.deleteQuietly(file);
            }
        }
    }

    private static File transfer(FFMpegUtil ffmu, String extension) throws IOException {

        if (StringUtils.equals(FilenameUtils.getExtension(ffmu.getOriginFileUri()), extension)) {
            return new File(ffmu.getOriginFileUri());
        } else {
            File file = File.createTempFile("tmp", extension);

            ffmu.transfer(file.getAbsolutePath());
            return file;
        }
    }
}
